package com.fun.mysql;

import com.fun.httpclient.FanLibrary;
import com.fun.httpclient.RequestInfo;
import com.fun.profile.Constant;
import com.fun.profile.SqlConstant;
import com.fun.profile.SysInit;
import com.fun.utils.DecodeEncode;
import com.fun.utils.Time;
import com.fun.utils.message.AlertOver;
import net.sf.json.JSONObject;

import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.concurrent.LinkedBlockingDeque;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * 数据库读写类
 *
 * @Author [Vicky]
 * @Description
 * @UpdateRemark
 * @UpdateDate: [2018年1月10日 下午4:05:16]
 * @CreateDate: [2018年1月10日 下午4:05:16]
 */
public class MySqlTest extends SqlBase {
    /**
     * 控台statement1和statement均衡
     */
    static AtomicInteger key = new AtomicInteger(0);

    /**
     * 存放数据库存储任务
     */
    static LinkedBlockingDeque<String> sqls = new LinkedBlockingDeque<>();

    public static Connection getConnection0() {
        return connection0;
    }

    public static Statement getStatement0() {
        return statement0;
    }

    /**
     * 用于查询
     */
    static Connection connection0;
    /**
     * 用于写入
     */
    static Connection connection1;
    /**
     * 用于写入
     */
    static Connection connection2;
    static Statement statement0;
    static Statement statement1;
    static Statement statement2;


    /**
     * 新方法，报错requestinfo对象
     *
     * @param requestInfo  请求信息
     * @param data_size
     * @param elapsed_time
     * @param status
     * @param mark
     * @param code
     * @param localIP
     * @param computerName
     */
    public static void saveApiTestDate(RequestInfo requestInfo, long data_size, double elapsed_time, int status, int mark, int code, String localIP, String computerName) {
        if (SysInit.isBlack(requestInfo.getHost()) || SqlConstant.REQUEST_TABLE == null) return;
        String sql = String.format("INSERT INTO " + SqlConstant.REQUEST_TABLE + " (host_name,api_name,data_size,elapsed_time,status,type,method,code,local_ip,computer_name,create_time) VALUES ('%s','%s',%d,%f,%d,'%s','%s',%d,'%s','%s','%s');", requestInfo.getHost(), requestInfo.getApiName(), data_size, elapsed_time, status, requestInfo.getType(), requestInfo.getMethod(), code, localIP, computerName, Time.getDate());
        sendWork(sql);
    }

    /**
     * 保存测试结果
     *
     * @param label  测试标记
     * @param result 测试结果
     */
    public static void saveTestResult(String label, JSONObject result) {
        if (SqlConstant.RESULT_TABLE == null) return;
        String data = result.toString();
        Iterator<String> iterator = result.keys();
        int abc = 1;
        while (iterator.hasNext() && abc == 1) {
            String key = iterator.next().toString();
            String value = result.getString(key);
            if (value.equals("false")) abc = 2;
        }
        if (abc != 1) new AlertOver("用例失败！", label + "测试结果：" + abc + Constant.LINE + data).sendBusinessMessage();
        output(label + Constant.LINE + "测试结果：" + (abc == 1 ? "通过" : "失败") + Constant.LINE + data);
        String sql = String.format("INSERT INTO " + SqlConstant.RESULT_TABLE + " (result,label,params,local_ip,computer_name,create_time) VALUES (%d,'%s','%s','%s','%s','%s')", abc, label, data, Constant.LOCAL_IP, Constant.COMPUTER_USER_NAME, Time.getDate());
        sendWork(sql);
    }

    /**
     * 记录alertover警告
     *
     * @param requestInfo
     * @param type
     * @param title
     * @param localIP
     * @param computerName
     */
    public static void saveAlertOverMessage(RequestInfo requestInfo, String type, String title, String localIP, String computerName) {
        String host_name = requestInfo.getHost();
        if (SysInit.isBlack(host_name) || SqlConstant.REQUEST_TABLE == null) return;
        String sql = String.format("INSERT INTO alertover (type,title,host_name,api_name,local_ip,computer_name,create_time) VALUES('%s','%s','%s','%s','%s','%s','%s');", type, title, host_name, requestInfo.getApiName(), localIP, computerName, Time.getDate());
        sendWork(sql);
    }

    /**
     * 获取所有有效的用例类
     *
     * @return
     */
    public static List<String> getAllCaseName() {
        List<String> list = new ArrayList<>();
        if (SqlConstant.CLASS_TABLE == null) return list;
        String sql = "SELECT * FROM " + SqlConstant.CLASS_TABLE + " WHERE flag = 1 ORDER BY create_time DESC;";
        TestConnectionManage.getQueryConnection();
        ResultSet resultSet = excuteQuerySql(connection0, statement0, sql);
        try {
            while (resultSet != null && resultSet.next()) {
                String className = resultSet.getString("class");
                list.add(className);
            }
        } catch (SQLException e) {
            output(sql, e);
        }
        return list;
    }

    /**
     * 获取用例状态
     *
     * @param name
     * @return
     */
    public static boolean getCaseStatus(String name) {
        if (SqlConstant.CLASS_TABLE == null) return false;
        String sql = "SELECT flag FROM " + SqlConstant.CLASS_TABLE + " WHERE class = \"" + name + "\";";
        TestConnectionManage.getQueryConnection();
        ResultSet resultSet = excuteQuerySql(connection0, statement0, sql);
        try {
            if (resultSet != null && resultSet.next()) {
                int flag = resultSet.getInt(1);
                return flag == 1 ? true : false;
            }
        } catch (SQLException e) {
            output(sql, e);
        }
        return false;
    }


    /**
     * 确保所有的储存任务都结束
     */
    private static void check() {
        int size = sqls.size();
        while (sqls.size() != 0) {
            sleep(100);
        }
        TestConnectionManage.stopAllThread();
    }

    /**
     * 执行sql语句，非query语句，并不关闭连接
     *
     * @param sql
     * @param key
     */
    static void excuteUpdateSql(String sql, boolean key) {
        int size = getWaitWorkNum();
        if (size % 3 == 1 && size > MySqlObject.getThreadNum() * (SqlConstant.MYSQL_WORK_PER_THREAD + 1) && size < SqlConstant.MYSQL_MAX_WAIT_WORK)
            new AidThread().start();
        if (key) {
            TestConnectionManage.getUpdateConnection1();
            excuteUpdateSql(connection1, statement1, sql);
            TestConnectionManage.updateLastUpdate1();
        } else {
            TestConnectionManage.getUpdateConnection2();
            excuteUpdateSql(connection2, statement2, sql);
            TestConnectionManage.updateLastUpdate2();
        }
    }

    /**
     * 发送数据库任务，暂时用请求服务器接口
     *
     * @param sql
     * @return
     */
    public static void sendWork(String sql) {
        JSONObject argss = new JSONObject();
        argss.put("sql", DecodeEncode.urlEncoderText(sql));
        FanLibrary.getHttpResponse(FanLibrary.getHttpPost(SqlConstant.MYSQL_SERVER_PATH, argss));
    }

    /**
     * 添加存储任务，数据库存储服务用
     *
     * @param sql
     * @return
     */
    public static boolean addWork(String sql) {
        try {
            sqls.put(sql);
        } catch (InterruptedException e) {
            output("添加数据库存储任务失败！", e);
            return false;
        }
        return true;
    }

    /**
     * 从任务池里面获取任务
     *
     * @return
     */
    static String getWork() {
        String sql = null;
        try {
            sql = sqls.poll(SqlConstant.MYSQLWORK_TIMEOUT, TimeUnit.MILLISECONDS);
        } catch (InterruptedException e) {
            output("获取存储任务失败！", e);
        } finally {
            return sql;
        }
    }

    /**
     * 获取等待任务数
     *
     * @return
     */
    public static int getWaitWorkNum() {
        return sqls.size();
    }

    /**
     * 提供外部查询功能
     *
     * @param sql
     * @return
     */
    public static ResultSet excuteQuerySql(String sql) {
        TestConnectionManage.getQueryConnection();
        return excuteQuerySql(connection0, statement0, sql);
    }


    /**
     * 关闭数据库链接的方法，供外部使用
     */
    public static void mySqlOver() {
        mySqlQueryOver();
    }

    /**
     * 关闭update连接
     */
    static void mySqlUpdateOver() {
        check();
        mySqlOver(connection1, statement1);
        mySqlOver(connection2, statement2);
    }

    /**
     * 关闭query连接
     */
    public static void mySqlQueryOver() {
        mySqlOver(connection0, statement0);
    }
}
